package com.nokia.example3dgame;

import javax.microedition.m3g.*;

public class FloorTiles {

	private Mesh floorMesh;

	public FloorTiles(Image2D floorIm, int sz) {
		/*
		 * Make sure the size value is divisible by 2, since we'll use size/2
		 * later.
		 */
		int size = (sz / 2) * 2;
		if (size != sz)
			System.out.println("Size set to multiple of 2: " + size);

		int numTiles = size * size;
		/*
		 * Each tile is a 1-by-1 quadrilateral (quad), so numTiles of them will
		 * cover a size-by-size floor.
		 */

		// build the floor mesh
		VertexBuffer floorVertBuf = makeGeometry(size, numTiles);

		IndexBuffer floorIdxBuf = new TriangleStripArray(
				makeIndicies(numTiles), makeStripLens(numTiles));

		Appearance floorApp = makeAppearance(floorIm);

		floorMesh = new Mesh(floorVertBuf, floorIdxBuf, floorApp);
	} // end of TiledFloor()

	private VertexBuffer makeGeometry(int size, int numTiles)
	/*
	 * numTiles squares centered at the origin on the XZ plane. Normals aren't
	 * required since the floor doesn't reflect light.
	 */
	{
		// create vertices
		short[] verts = makeVerts(size, numTiles);
		VertexArray va = new VertexArray(verts.length / 3, 3, 2);
		va.set(0, verts.length / 3, verts);

		// create texture coordinates
		short[] tcs = makeTexCoords(numTiles);
		VertexArray texArray = new VertexArray(tcs.length / 2, 2, 2);
		texArray.set(0, tcs.length / 2, tcs);

		VertexBuffer vb = new VertexBuffer();
		vb.setPositions(va, 1.0f, null); // no scale, bias
		vb.setTexCoords(0, texArray, 1.0f, null);

		return vb;
	} 

	private short[] makeVerts(int size, int numTiles)
	
	{
		short[] verts = new short[12 * numTiles]; // 3 * 4 points for each tile
		int i = 0;
		for (int z = (-size / 2) + 1; z <= size / 2; z++)
			for (int x = -size / 2; x <= (size / 2) - 1; x++) {
				verts[i] = (short) x;
				verts[i + 1] = 0;
				verts[i + 2] = (short) z;
				verts[i + 3] = (short) (x + 1);
				verts[i + 4] = 0;
				verts[i + 5] = (short) z;
				verts[i + 6] = (short) (x + 1);
				verts[i + 7] = 0;
				verts[i + 8] = (short) (z - 1);
				verts[i + 9] = (short) x;
				verts[i + 10] = 0;
				verts[i + 11] = (short) (z - 1);
				i += 12;
			}
		return verts;
	} 

	private short[] makeTexCoords(int numTiles)
	
	{
		short[] tcs = new short[8 * numTiles]; // 2 * 4 points for each tile
		for (int i = 0; i < 8 * numTiles; i += 8) { // {0,1, 1,1, 1,0, 0,0}
			tcs[i] = 0;
			tcs[i + 1] = 1; // for each tile
			tcs[i + 2] = 1;
			tcs[i + 3] = 1;
			tcs[i + 4] = 1;
			tcs[i + 5] = 0;
			tcs[i + 6] = 0;
			tcs[i + 7] = 0;
		}
		return tcs;
	} 

	private int[] makeIndicies(int numTiles)
	
	{ // positions for first tile: {1,2,0,3}
		int pos1 = 1;
		int pos2 = 2;
		int pos3 = 0;
		int pos4 = 3;

		int[] idxs = new int[4 * numTiles]; // 4 points for each tile
		for (int i = 0; i < 4 * numTiles; i += 4) {
			idxs[i] = pos1;
			pos1 += 4; // increment the positions by 4
			idxs[i + 1] = pos2;
			pos2 += 4;
			idxs[i + 2] = pos3;
			pos3 += 4;
			idxs[i + 3] = pos4;
			pos4 += 4;
		}
		return idxs;
	} 

	private int[] makeStripLens(int numTiles)

	{
		int[] lens = new int[numTiles];
		for (int i = 0; i < numTiles; i++)
			lens[i] = 4;
		return lens;
	}

	private Appearance makeAppearance(Image2D floorIm)
	// No Material, with the texture clamped to each tile
	{
		Appearance app = new Appearance();

		if (floorIm != null) {
			Texture2D tex = new Texture2D(floorIm);
			tex
					.setFiltering(Texture2D.FILTER_NEAREST,
							Texture2D.FILTER_NEAREST);
			tex.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
			app.setTexture(0, tex);
		}

		// add perspective correction
		PolygonMode floorPolygonMode = new PolygonMode();
		floorPolygonMode.setPerspectiveCorrectionEnable(true);
		// floorPolygonMode.setCulling(PolygonMode.CULL_NONE); // switch off
		// culling

		app.setPolygonMode(floorPolygonMode);

		return app;
	} 


	public Mesh getFloorMesh() {
		return floorMesh;
	}

} 
